#include "MRMesh.h"
#include <iostream>
using namespace std;

MRChart::MRChart(int index, int depth, int min_chart, int sec_w, int sec_h, 
				 float dx, float dist, int bb_x, int bb_y, MRCamera cam,
				 Image *pp, Image *nn, Image *cc)
{
	this->index = index;
	this->depth = depth;

	this->dx = dx;
	this->dist = dist;
	this->bb_x = bb_x;
	this->bb_y = bb_y;
	this->cam = cam;
	p = pp;
	n = nn;
	c = cc;

	sections_w = sec_w;
	sections_h = sec_h;
	num_tops = sections_w*sections_h;
	
	top = (MRSection **) malloc (num_tops*sizeof(MRSection *));
	for(int i=0; i<num_tops; i++)
		top[i] = new MRSection(0,depth);

	generate_tree();
}

void MRChart::generate_tree()
{
	int w = p->GetW();
	int h = p->GetH();
	int sec_sizew = (int)((float)w/(float)sections_w);
	int sec_sizeh = (int)((float)h/(float)sections_h);
	int counter = 0;

	Image *ptmp = new Image(sec_sizew, sec_sizeh);
	Image *ntmp = new Image(sec_sizew, sec_sizeh);
	Image *ctmp = new Image(sec_sizew, sec_sizeh);

	for(int i=0; i<sections_w; i++)
	{
		for(int j=0; j<sections_h; j++)
		{
			int ex=0, ey=0;
			if(i==sections_w-1)
				ex=w%sections_w;
			if(j==sections_h-1)
				ey=h%sections_h;
			ptmp->LoadSubImage(p, i*sec_sizew, j*sec_sizeh, sec_sizew+ex, sec_sizeh+ey);
			ntmp->LoadSubImage(n, i*sec_sizew, j*sec_sizeh, sec_sizew+ex, sec_sizeh+ey);
			ctmp->LoadSubImage(c, i*sec_sizew, j*sec_sizeh, sec_sizew+ex, sec_sizeh+ey);
			top[counter]->compute_splats(bb_x+i*sec_sizew,
															bb_y+ j*sec_sizeh, 
															sec_sizew+ex, sec_sizeh+ey, 
															0, 0, ptmp, ntmp, ctmp, cam, dist, dx);
			counter++;
		}
	}

	int num_splats=0;
	for(int i=0; i<num_tops; i++)
		if(top[i]->num_splats>0)
			num_splats++;

	counter =0;
	MRSection **new_top = (MRSection **) malloc (num_splats*sizeof(MRSection *));
	for(int i=0; i<num_tops; i++)
		if(top[i]->num_splats>0)
		{
			new_top[counter]=top[i];
			counter++;
		}
	top = new_top;
	num_tops = num_splats;

	compute_aabb();
}

void MRChart::compute_aabb()
{
	d_Vec3f min = d_Vec3f(  10000, 10000, 10000);
	d_Vec3f max = d_Vec3f(-10000,-10000,-10000);
	for(int i=0; i<num_tops; i++)
	{
		if(top[i]->aabb->min[0]<min[0])
			min[0] = top[i]->aabb->min[0];
		if(top[i]->aabb->max[0]>max[0])
			max[0] = top[i]->aabb->max[0];
		if(top[i]->aabb->min[1]<min[1])
			min[1] = top[i]->aabb->min[1];
		if(top[i]->aabb->max[1]>max[1])
			max[1] = top[i]->aabb->max[1];
		if(top[i]->aabb->min[2]<min[2])
			min[2] = top[i]->aabb->min[2];
		if(top[i]->aabb->max[2]>max[2])
			max[2] = top[i]->aabb->max[2];
	}
	aabb = new d_AABB(min,max);
}

void MRChart::draw(int d, d_Frustum *frustum)
{
		if(frustum->boxInFrustum(aabb)==INSIDE)
			for(int i=0; i<num_tops; i++)
				top[i]->draw(d, frustum);
}

void MRChart::draw(int d)
{
		for(int i=0; i<num_tops; i++)
			top[i]->draw(d);
}

Splat MRChart::get_average_splat()
{
	Splat res;
	res.vp = res.n = res.c = d_Vec3f(0,0,0);
	for(int i=0; i<num_tops; i++)
		res = res + top[i]->get_average_splat();
	res.n = norm(res.n);
	return res/(float)(num_tops);
}

